// Copyright (C) Microsoft Corporation. All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;

namespace Microsoft.VSPowerToys.VSCmdShell.UnitTests
{
    /// <summary>
    /// Unit tests for the WrappingCollection object.
    /// </summary>
    [TestFixture]
    public class WrappingCollectionTests
    {
        private WrappingCollection<int> testCollection;

        [SetUp]
        public void Setup()
        {
            this.testCollection = new WrappingCollection<int>();
        }

        /// <summary>
        /// Testing wrapping of the list when list contains only a single item.
        /// </summary>
        [Test]
        public void AddSingleItems()
        {
            this.testCollection.AddLast(5);
            Assert.AreEqual(5, this.testCollection.Next);
            Assert.AreEqual(5, this.testCollection.Next);
            Assert.AreEqual(5, this.testCollection.Next);
            Assert.AreEqual(5, this.testCollection.Next);
        }

        /// <summary>
        /// Testing wrapping of the list when list contains multiple items.
        /// </summary>
        [Test]
        public void MultipleItemsWrappingTest()
        {
            for (int i = 0; i < 10; i++)
            {
                this.testCollection.AddLast(i);
            }
            for (int i = 0; i < 10; i++)
            {
                Assert.AreEqual(i, this.testCollection.Next);
            }
            for (int i = 9; i >= 0; i--)
            {
                Assert.AreEqual(i, this.testCollection.Previous);
            }

        }

        /// <summary>
        /// Testing if clear, clears the list correctly and resets the current node
        /// pointer as well.
        /// </summary>
        [Test]
        public void MultipleItemsAfterClear()
        {
            MultipleItemsWrappingTest();
            int x = this.testCollection.Next;
            this.testCollection.Clear();
            MultipleItemsWrappingTest();
        }

        /// <summary>
        /// Testing if removing in an item resets the current node pointer correctly.
        /// </summary>
        [Test]
        public void MultipleItemsRemoveItem()
        {
            for (int i = 0; i < 10; i++)
            {
                this.testCollection.AddLast(i);
            }
            for (int i = 0; i < 5; i++)
            {
                Assert.AreEqual(i, this.testCollection.Next);
            }
            this.testCollection.Remove(5);
            for (int i = 9; i >= 0; i--)
            {
                if (i == 5) continue;
                Assert.AreEqual(i, this.testCollection.Previous);
            }
            for (int i = 0; i < 10; i++)
            {
                if (i == 5) continue;
                Assert.AreEqual(i, this.testCollection.Next);
            }
            
        }

        /// <summary>
        /// Testing if adding an item using CurrentNode pointer works correctly. Add operation
        /// immediatly affects Next and Previous operations since the position of the current
        /// node is not reset.
        /// </summary>
        [Test]
        public void MultipleItemsAddItemInMiddle()
        {
            for (int i = 0; i < 10; i++)
            {
                this.testCollection.AddLast(i);
            }
            for (int i = 0; i < 5; i++)
            {
                Assert.AreEqual(i, this.testCollection.Next);
            }
            this.testCollection.AddAfter(this.testCollection.CurrentNode, 11);
            for (int i = 5; i < 10; i++)
            {
                
                Assert.AreEqual(i, this.testCollection.Next);
                if (i == 5)
                {
                    Assert.AreEqual(11, this.testCollection.Next);
                }
            }
            for (int i = 9; i >= 0; i--)
            {

                if (i == 5)
                {
                    Assert.AreEqual(11, this.testCollection.Previous);
                }
                Assert.AreEqual(i, this.testCollection.Previous);
                
            }
      
        }

        #region Tests - Testing expected exceptions

        /// <summary>
        /// Testing if calling Next on an empty list throws InvalidOperationException
        /// </summary>
        [ExpectedException(typeof(InvalidOperationException)), Test]
        public void EmptyListNextItem()
        {
            int i = this.testCollection.Next;
        }

        /// <summary>
        /// Testing if calling Previous on an empty list throws InvalidOperationException
        /// </summary>
        [ExpectedException(typeof(InvalidOperationException)), Test]
        public void EmptyListPreviousItem()
        {
            int i = this.testCollection.Previous;
        }

        #endregion


    }
}
